//
// Created by DELL on 2024/6/13.
//

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <vector>

// 字符串解码 ABC[2|C[3|DF]]G
// 结果： ABCCDFDFDFCDFDFDFG
// 字符串只包含 大写字母、数字、[、]、|

// 解码一对中括号 [2|B], 返回BB
std::string decompressionInner(const std::string& str, int start, int end)
{
    std::string result;
    if (start >end || start >= str.size() || end >= str.size())
    {
        return result;
    }

    int i = start;
    while (i <= end)
    {
        if (str[i] == '[')
        {
            int num = 0;
            int base = 1;
            ++i; // 跳过 ‘[’
            while ('0' <= str[i] && str[i] <= '9')
            {
                num = num * base + (str[i] - '0');
                base *= 10;
                ++i;
            }
            ++i; // 跳过 ‘|’

            int j = i;
            int n = 1;
            while (n > 0 && j <= end)
            {
                ++j;
                if (str[j] == '[')
                {
                    ++n;
                }
                else if (str[j] == ']')
                {
                    --n;
                }
            }
            auto temp = decompressionInner(str, i, j - 1);
            i = j + 1;
            for (j = 0; j < num; ++j)
            {
                result += temp;
            }
        }
        else if (std::isalpha(str[i]))
        {
            result += str[i];
            ++i;
        }
        else
        {
            ++i;
        }
    }

    return result;
}

std::string decompression1(const std::string& str)
{
    return decompressionInner(str, 0, (int)str.size() - 1);
}


std::string decompression2(const std::string& str)
{
    std::string result;
    std::vector<int> nums;

    for (int i = 0; i < str.size(); )
    {
        auto c = str[i];
        if (c == '[')
        {
            int n = 0;
            int base = 1;
            ++i; // 跳过 [
            while ('0' <= str[i] && str[i] <= '9')
            {
                n = n * base + (str[i] - '0');
                base *= 10;
                ++i;
            }
            ++i; // 跳过 |
            result.push_back('|');
            nums.push_back(n);
        }
        else if (c == ']')
        {
            auto pos = result.rfind('|');
            auto temp = result.substr(pos + 1);
            result.erase(pos);
            int n = nums.back();
            nums.pop_back();
            for (int j = 0; j < n; ++j)
            {
                result += temp;
            }
            ++i;
        }
        else if ('A' <= c && c <= 'Z')
        {
            result.push_back(c);
            ++i;
        }
        else
        {
            ++i;
        }

    }
//    assert(nums.empty());
    return result;
}

int main()
{
    constexpr const char* strings[] = {  "[12|A]","AB[2|CD]F", "AB[2|CD[3|G]]", "AB[2|CD[3|G]]F",
                                       "[2|AB[2|CD[3|G]]]", "[2|AB[2|CD[3|G]F]H]K"};

    for (auto str : strings)
    {
        std::cout << "Compression String: " << str << std::endl;
        std::cout << "decompression1 Recursion: " << decompression1(str) << std::endl;
        std::cout << "decompression2 Stack:     " << decompression2(str) << std::endl;
        std::cout << "---------------------" << std::endl;
    }

    constexpr const char* testStr = "-123|35";
    std::string_view testStrView = testStr;
    std::cout << "testStr=\"" << testStr << '"' << std::endl;

    int n = atoi(testStr);
    std::cout << "atoi(str), return:" << n << std::endl;

    size_t pos = 0;
    const char* start = testStr;
    while (std::isalnum(*start) || *start == '-' || *start == '+')
    {
        //  n = std::stoi(testStrView, &pos); // compile error
        n = std::stoi(start, &pos);
        std::cout << "std::stoi(str, &pos), return:" << n << " , pos: " << pos << std::endl;

        start = start + pos;
        ++start;
    }

    const char* begin = testStr;
    char* end = nullptr;
    while (true)
    {
        n = strtol(begin, &end, 10);
        if (begin == end)
        {
            break;
        }
        std::cout << "strtol(begin, &end, 10), return:" << n << std::endl;
        ++end;
        begin = end;
    }


    return 0;
}